/* Copyright © 2010 LPRM
Universidade Federal do Espírito Santo - RNP-GT CWTools

This file is part of GW-Android.

GW-Android is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

GW-Android is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with GW-Android. If not, see <http://www.gnu.org/licenses/>. */
package br.ufes.cwtools.gw.android.components.binomial;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import br.ufes.cwtools.gw.android.components.Component;
import br.ufes.cwtools.gw.android.connection_service.ConnectionServiceConnection;
import br.ufes.cwtools.gw.android.connection_service.IConnectionService;

public class Binomial extends Component {
	private final static String LOG_TAG = "Binomios";
	
	private static final String EXTRA_BINOMIOS = "br.ufes.inf.lprm.cwtools.gwa.components.binomial.Binomial.binomios";
	private static final String BINOMIAL_EVALUATE_SUFIX = "/evaluateEntity";

	private static final String BINOMIOS_ARQUIGRAFIA =
		"Assimétrica/Simétrica, Côncavo/Convexo, Escuro/Claro, "
		+ "Fosco/Brilhante, Fragmentada/Concisa, Irregular/Regular, "
		+ "Monocromático/Colorido, Ortogonal/Curva, Perpendicular/Inclinada, "
		+ "Saliências/Reentrâncias, Simples/Complexa, Transparente/Opaco";
	
	// Chaves para o Map que armazena os dados na View através de setTag().
	private static final String KEY_LEFT_TEXT_VIEW = "leftTextView";
	private static final String KEY_RIGHT_TEXT_VIEW = "rightTextView";
	private static final String KEY_BINOMIO = "binomio";

	private String binomialPostUrl;
	
	private List<Binomio> binomios = null;
	private Long photoId;
	private String photoClass;
	private ConnectionServiceConnection binomialConn;
	private Button sendButton;
	private ProgressDialog dialog;
	private boolean cancelled = false;
	private String lastRequest;
	
	private static final int MSG_FINISH = 101;
	private static final int MSG_UPDATE_UI_POST = 102;
	private Handler bHandler = new Handler(){
		@Override
		public void handleMessage(Message msg) {
			switch(msg.what){
				case MSG_FINISH:
					resetUI();
					finish();
					break;
				case MSG_UPDATE_UI_POST:
					sendButton.setEnabled(false);
					dialog = new ProgressDialog(Binomial.this);
					dialog.setTitle("Enviando binômios");
					dialog.setMessage("Configurando a foto recém enviada.");
					dialog.setIndeterminate(true);
					dialog.setCancelable(true);
					dialog.setOnCancelListener(new OnCancelListener() {
						@Override
						public void onCancel(DialogInterface dialog) {
							resetUI();
						}
					});
					dialog.show();
					break;
			}
		}
	};
	
	private void resetUI(){
		sendButton.setEnabled(true);
		dialog.dismiss();
		dialog = null;
		unbindService(binomialConn);
		cancelled = true;
	}
	
	@SuppressWarnings("unchecked")  // Por causa do cast com generics.
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		setContentView(R.layout.binomios);
		LinearLayout container = (LinearLayout) this.findViewById(R.id.binomios_container);
		sendButton = (Button) findViewById(R.id.binomios_send_button);

		try{
			photoClass = getConfiguration(EXTRA_ENTITY_CLASS);
			photoId = Long.valueOf(getConfiguration(EXTRA_ENTITY_ID));
		}catch(Exception e){
			Log.e(LOG_TAG, "Erro: photoId e photoClass corrompidos ou não especificados.", e);
			Toast.makeText(this, "Erro ao inferir id e/ou classe da foto recém enviada.", Toast.LENGTH_LONG).show();
			fail();
			return;
		}
		
		binomialPostUrl = getConfiguration(EXTRA_APPLICATION_URL) + getConfiguration(EXTRA_BASE_URL) + BINOMIAL_EVALUATE_SUFIX;
		
		binomios = (List<Binomio>) getLastNonConfigurationInstance();
		
		if (binomios == null) {
			binomios = new LinkedList<Binomio>();
			final String sExtraBinomios = getConfiguration(EXTRA_BINOMIOS);
			// Tenta carregar a configuração dos binômios; se não encontra, usa os valores em BINOMIOS_ARQUIGRAFIA como fallback.
			final String[] sBinomios = (sExtraBinomios != null ? sExtraBinomios : BINOMIOS_ARQUIGRAFIA).split(",");
			for (final String sBinomio : sBinomios) {
				final String[] s = sBinomio.split("/");
				if (s.length == 2)
					binomios.add(new Binomio(s[0].trim(), s[1].trim()));
			}
		}
		
		for (final Binomio binomio : binomios) {
			final View v = getLayoutInflater().inflate(R.layout.binomio, null);
			container.addView(v);
			//A view está invertida no site também, é proposital (eu acho)!
			((TextView) v.findViewById(R.id.label_left)).setText(binomio.getRight());
			((TextView) v.findViewById(R.id.label_right)).setText(binomio.getLeft());
			final TextView seekbarLeftValueText = (TextView) v.findViewById(R.id.seekbar_value_left);
			seekbarLeftValueText.setText(Integer.toString(binomio.getRightValue()) + "%");
			final TextView seekbarRightValueText = (TextView) v.findViewById(R.id.seekbar_value_right);
			seekbarRightValueText.setText(Integer.toString(binomio.getLeftValue()) + "%");
			final SeekBar seekbar = (SeekBar) v.findViewById(R.id.seekbar);
			seekbar.setHorizontalScrollBarEnabled(true);
			
			final HashMap<String, Object> tag = new HashMap<String, Object>(3);
			tag.put(KEY_LEFT_TEXT_VIEW, seekbarLeftValueText);
			tag.put(KEY_RIGHT_TEXT_VIEW, seekbarRightValueText);
			tag.put(KEY_BINOMIO, binomio);
			seekbar.setTag(tag);
			
			seekbar.setProgress(binomio.getLeftValue());
			seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
				@Override
				public void onStopTrackingTouch(SeekBar seekBar) { }
				
				@Override
				public void onStartTrackingTouch(SeekBar seekBar) { }
				
				@Override
				public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
					final HashMap<String, Object> tag = (HashMap<String, Object>) seekBar.getTag();
					final Binomio binomio = (Binomio) tag.get(KEY_BINOMIO);
					binomio.setLeftValue(progress);
					((TextView) tag.get(KEY_LEFT_TEXT_VIEW)).setText(Integer.toString(binomio.getRightValue()) + "%");
					((TextView) tag.get(KEY_RIGHT_TEXT_VIEW)).setText(Integer.toString(binomio.getLeftValue()) + "%");
				}
			});
		}
		
		binomialConn = new ConnectionServiceConnection(Binomial.class.getName()) {
			
			@Override
			public void onServiceConnected() {
				if (binomios != null){
					//Cria as variáveis necessárias no post
					Bundle params = new Bundle();
					params.putString("entityId", photoId.toString());
					params.putString("entityClass", photoClass);
					int i=0;
					for(Binomio b : binomios){
						params.putString("binomials[" + i + "].firstName", b.getLeft());
						params.putString("binomials[" + i + "].secondName", b.getRight());
						params.putString("binomials[" + i + "].value", Integer.toString(b.getLeftValue()));
						i++;
					}
					
					try{
						lastRequest = ConnectionServiceConnection.generateId(); 
						registerPostRequest(binomialPostUrl, lastRequest, params, null);
						bHandler.sendEmptyMessage(MSG_UPDATE_UI_POST);
					}catch(Exception e){
						Log.e(LOG_TAG, "Erro no post dos binômios!", e);
					}
				}
			}
			
			@Override
			public void onRequestFinished(String id, String filePath) {
				if (!cancelled && id.equals(lastRequest)){
					//TODO: Validar a resposta do servidor
					bHandler.sendEmptyMessage(MSG_FINISH);
				}
			}
		};
	}
	
	@Override
	public Object onRetainNonConfigurationInstance() {
		return this.binomios;
	}

	public void doneOnClick(View view) {
		cancelled = false;
		bindService(new Intent(IConnectionService.class.getName()), binomialConn, Context.BIND_AUTO_CREATE);
	}
}

class Binomio {
	private final String left;
	private final String right;
	private int leftValue;
	private static final int DEFAULT_VALUE = 50;
	private static final int MAX_VALUE = 100;
	
	public Binomio(String left, String right) {
		this.left = left;
		this.right = right;
		this.leftValue = DEFAULT_VALUE;
	}
	
	public String getLeft() {
		return left;
	}
	
	public String getRight() {
		return right;
	}
	
	public int getLeftValue() {
		return leftValue;
	}

	public void setLeftValue(int value) {
		this.leftValue = value;
	}
	
	public int getRightValue() {
		return MAX_VALUE - leftValue;
	}
}
